﻿using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Xml;
using EyFramework.Common;
using ShuJuGj.Entity;
using ShuJuGj.Entity.InData;
using ShuJuGj.Entity.OutData;
using ShuJuGj.Core.Service;
using Exception = System.Exception;

namespace ShuJuGj
{
    public delegate void ShowLoadingText(string text);

    /// <summary>
    /// 数据上传服务封装
    /// </summary>
    public class UploadService
    {
        private ISjgjShujujiService shujujiService = Globals.GetService<ISjgjShujujiService>();
        private ITjTjbgPdfService tjbgPdfService = Globals.GetService<ITjTjbgPdfService>();
        private ISjgjJktjbgjlService tjbgJktjbgjlService = Globals.GetService<ISjgjJktjbgjlService>();
        public ShowLoadingText showLoadingText;

        /// <summary>
        /// 每/条记录，分作一次任务
        /// </summary>
        private int perCount = 5000;

        /// <summary>
        /// 上传数据集
        /// </summary>
        /// <returns></returns>
        public void UploadData()
        {
            List<SjgjShujuji> sjjList = shujujiService.GetNeedUploadSjj("1");
            foreach (SjgjShujuji sjj in sjjList)
            {
                UploadDataSet(sjj);
            }
        }

        /// <summary>
        /// 实时上传数据集
        /// </summary>
        public void UploadDataTime()
        {
            List<SjgjShujuji> sjjList = shujujiService.GetNeedUploadSjj("2");
            foreach (SjgjShujuji sjj in sjjList)
            {
                UploadDataSet(sjj);
            }
        }

        public void UploadDataSet(SjgjShujuji sjj)
        {
            try
            {
                Logger.Debug(string.Format("开始上传数据集:{0}", sjj.TBNAME));
                showLoadingText(string.Format("开始上传数据集:{0}", sjj.YWMC));
                int totRecord = shujujiService.GetTotRecord(sjj);
                int successRecord = 0;
                int failRecord = 0;
                if (totRecord > 0)
                {
                    //1、查询获取所有的字段列
                    List<ColumnInfo> columns = shujujiService.GetColumnInfo(sjj.CONNECT_TYPE, sjj.TBNAME);
                    //获取任务数
                    int sn = (totRecord / perCount) + (totRecord % perCount > 0 ? 1 : 0);
                    int UploadRecod = perCount;
                    int hasUploadRecord = 0;
                    List<SjgjUploadData> sulds = new List<SjgjUploadData>();
                    using (DataTable data = shujujiService.GetUploadData(sjj))
                    {
                        //1、获取批次任务号
                        string taskId = GetPatchTaskId(sjj, totRecord, sn);
                        for (int i = 0; i < sn; i++)
                        {
                            showLoadingText(string.Format("共{0}条记录需要上传,正在传{1}/{2},请稍后...", totRecord, i + 1, sn));
                            sulds.Clear();
                            if (i == sn - 1)
                            {
                                //如果是最后一次,则上传的数量为,中数量减去-已上传的数量。剩下的全部上传
                                UploadRecod = totRecord - perCount * i;
                            }
                            else
                            {
                                UploadRecod = perCount;
                            }

                            //2、获取单次任务号
                            string singleTaskId = GetSingleTaskId(sjj, taskId, i + 1, UploadRecod);
                            //3、调用数据集上传

                            StringBuilder xmlData =
                                new StringBuilder("<dmp><datasets><settype/><setcode>" + sjj.SJJBM + "</setcode>");
                            for (int j = hasUploadRecord; j < hasUploadRecord + UploadRecod; j++)
                            {
                                SjgjUploadData suld = new SjgjUploadData();
                                suld.BATCH_TASK_ID = taskId;
                                suld.TASK_ID = singleTaskId;
                                suld.SJJSEQ = sjj.SEQ;
                                suld.TBNAME = sjj.TBNAME;
                                suld.YWMC = sjj.YWMC;
                                suld.DATA_KEY = GetDataKey(sjj, data.Rows[j]);
                                suld.UPLOAD_DATE = System.DateTime.Now;
                                sulds.Add(suld);
                                xmlData.Append(GetXmlData(data.Rows[j], columns));
                            }

                            xmlData.Append("</datasets></dmp>");
                            Logger.Debug("上传【" + sjj.YWMC + "】：\n入参:" + xmlData.ToString() + "\n");
                            //XmlData压缩
                            if (UploadXmlData(sjj, ZipHelper.GZipCompressString(xmlData.ToString()), singleTaskId))
                            {
                                shujujiService.SaveUploadData(sulds, sjj);
                                successRecord = successRecord + UploadRecod;
                            }
                            else
                            {
                                failRecord = failRecord + UploadRecod;
                            }

                            hasUploadRecord = hasUploadRecord + UploadRecod;
                        }
                    }
                }

                Logger.Debug(string.Format("{0}数据集上传完毕，本次共有{1}条记录,成功:{2},失败:{3}条", sjj.TBNAME, totRecord, successRecord,
                    failRecord));
            }
            catch (Exception ex)
            {
                Logger.Error(string.Format("{0}数据集上传遇到异常,异常原因:{1}", sjj.TBNAME, ex.ToString()));
            }
        }

        /// <summary>
        /// 获取一条记录的唯一标志
        /// </summary>
        /// <returns></returns>
        private string GetDataKey(SjgjShujuji sjj, DataRow row)
        {
            string[] result = sjj.WYBZ.Split(new char[] { '^' });
            string keyData = string.Empty;
            foreach (string col in result)
            {
                if (!string.IsNullOrEmpty(keyData))
                {
                    keyData = keyData + "^" + row[col].ToString();
                }
                else
                {
                    keyData = row[col].ToString();
                }
            }

            return keyData;
        }

        private string GetXmlData(DataRow row, List<ColumnInfo> columns)
        {
            string xml =
                "<setdetails><BUSINESS_ID/><ORGANIZATION_CODE/><UPDATE_DATE/><DATAGENERATE_DATE/><ORGANIZATION_NAME/><BASIC_ACTIVE_ID/><RECORD_IDEN/><DOMAIN_CODE/><SERIALNUM_ID/><ARCHIVE_DATE/><CREATE_DATE/><BATCH_NUM/><LOCAL_ID/><TASK_ID/>";
            foreach (ColumnInfo ci in columns)
            {
                xml = xml + "<" + ci.ColumnName.ToUpper() + ">" +
                      handleXmlFlag(row[ci.ColumnName.ToUpper()].ToString()) + "</" + ci.ColumnName.ToUpper() + ">";
            }

            xml = xml + "</setdetails>";
            return xml;
        }

        private string handleXmlFlag(string xmlData)
        {
            if (!string.IsNullOrEmpty(xmlData))
            {
                return xmlData.Replace(">", "&gt;").Replace("<", "&lt;");
            }
            else
            {
                return string.Empty;
            }
        }

        /// <summary>
        /// 上传数据
        /// </summary>
        /// <param name="sjj"></param>
        /// <param name="columns"></param>
        private bool UploadXmlData(SjgjShujuji sjj, string xmlData, string taskId)
        {
            UploadInData ud = new UploadInData();
            ud.Servicecode = "SJCJCJE:SJSCE";
            ud.Standardcode = sjj.JHBZBM;
            ud.Daqtaskid = taskId;
            ud.XmlData = xmlData;
            string inXml = ud.GetInXml();
            inXml = $@"<soapenv:Envelope xmlns:soapenv=""http://schemas.xmlsoap.org/soap/envelope/"" xmlns:web=""http://webservice.entrance.si.neusoft.com/"">
                            <soapenv:Header/>
                            <soapenv:Body>
                            <web:handle>
                                <arg0><![CDATA[{inXml}]]></arg0>
                             </web:handle>
                           </soapenv:Body>
                        </soapenv:Envelope>";
            string outXml = CallWebService("http://195.195.8.170:8889/SJCJSJSCJKE/SJSCE", inXml, "text/xml");
            Logger.Debug("上传【" + sjj.YWMC + "】：出参:" + outXml + "\n");
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.LoadXml(outXml);
            DeclareOutData outData = new DeclareOutData(xmlDoc.InnerText);
            if (outData.Retcode != "1")
            {
                Logger.Info(string.Format("数据集:{0},上传失败,入参:{1},输出:{2}", sjj.YWMC, inXml, outXml));
                return false;
            }

            return true;
        }

        /// <summary>
        /// 获取单次任务号
        /// </summary>
        /// <param name="sjj">数据集</param>
        /// <param name="taskId">批次任务ID</param>
        /// <param name="sn">第几次上传</param>
        /// <param name="dataNum">本次上传记录数</param>
        /// <returns></returns>
        private string GetSingleTaskId(SjgjShujuji sjj, string taskId, int sn, int dataNum)
        {
            SingleDeclareInData sdid = new SingleDeclareInData();
            sdid.Servicecode = "SJCJCJE:HQDCRWHE";
            sdid.Daqtaskid = DateTime.Now.ToString("yyyyMMddHHmmssfff");
            sdid.Declaretype = "1";
            sdid.Totaltaskid = taskId;
            sdid.Colrescode = sjj.JHBZBM;
            sdid.Sn = sn.ToString();
            sdid.Setcode = sjj.SJJBM;
            sdid.Datanum = dataNum.ToString();
            string inXml = sdid.GetInXml();
            inXml = $@"<soapenv:Envelope xmlns:soapenv=""http://schemas.xmlsoap.org/soap/envelope/"" xmlns:col=""http://collectdeclareservice.webservice.entrance.si.neusoft.com/"">
                        <soapenv:Header />
                        <soapenv:Body >
                             <col:singleDeclare>
                                <arg0><![CDATA[{inXml}]]></arg0>
                            </col:singleDeclare>
                        </soapenv:Body>
                       </soapenv:Envelope>";
            string outXml = CallWebService("http://195.195.8.170:8889/SJCJHQRWHJKE/HQDCRWHE", inXml, "text/xml");
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.LoadXml(outXml);
            DeclareOutData outData = new DeclareOutData(xmlDoc.InnerText);
            return outData.TaskId;
        }

        /// <summary>
        /// 获取批次任务号
        /// </summary>
        /// <param name="sjj"></param>
        /// <param name="totRecord">共多少条记录</param>
        /// <param name="sn">分几次上传</param>
        /// <returns></returns>
        private string GetPatchTaskId(SjgjShujuji sjj, int totRecord, int sn)
        {
            TotalDeclareInData tdid = new TotalDeclareInData();
            tdid.Servicecode = "SJCJCJE:PCRWHHQE";
            tdid.Daqtaskid = DateTime.Now.ToString("yyyyMMddHHmmssfff");
            tdid.Collecttype = "0";
            tdid.Declaretype = "0";
            Totaldeclare td = new Totaldeclare();
            td.Colrescode = sjj.JHBZBM;
            td.Tasknum = sn.ToString();
            td.Begindatetime = DateTime.Now.AddDays(-1).ToString("yyyyMMdd") + "000000";
            td.Enddatetime = DateTime.Now.AddDays(-1).ToString("yyyyMMdd") + "235959";
            Declare de = new Declare();
            de.Setcode = sjj.SJJBM;
            de.Datanum = totRecord.ToString();
            td.Declares.Add(de);
            tdid.Totaldeclares.Add(td);
            string inXml = tdid.GetInXml();
            inXml = $@"<soapenv:Envelope xmlns:soapenv=""http://schemas.xmlsoap.org/soap/envelope/"" xmlns:col=""http://collectdeclareservice.webservice.entrance.si.neusoft.com/"">
                        <soapenv:Header />
                        <soapenv:Body >
                            <col:totalDeclare>
                                <arg0><![CDATA[{inXml}]]></arg0>
                            </col:totalDeclare>
                        </soapenv:Body>
                       </soapenv:Envelope>";
            string outXml = CallWebService("http://195.195.8.170:8889/SJCJHQRWHJKE/PCRWHHQE", inXml, "text/xml");
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.LoadXml(outXml);
            DeclareOutData outData = new DeclareOutData(xmlDoc.InnerText);
            return outData.TaskId;
        }

        /// <summary>
        /// 体检报告上传
        /// </summary>
        public void TjbgPdfUpload()
        {
            List<string> uploadDatas = tjbgPdfService.GetUnloadData();
            uploadDatas.ForEach(p =>
            {
                //获取需要上传的PDF
                var tjbgPdf = tjbgPdfService.GetTjbgPdf(p);
                if (tjbgPdf != null)
                {
                    var tjbg = tjbgJktjbgjlService.GetBgjlByTjbh(p);
                    UnFormatFile file = new UnFormatFile();
                    file.WS02_01_039_001 = tjbg.WS02_01_039_001;
                    file.WS02_01_906_01 = tjbg.WS02_01_030_01;
                    file.WS99_00_930_08 = tjbg.WS01_00_018_01;
                    file.WS01_00_018_01 = "47045202833010911A1001-" + tjbg.WS01_00_018_01;
                    file.WS99_99_034_46 = tjbg.WS01_00_018_01;
                    file.WS04_50_133_01 = tjbg.WS06_00_926_01.Substring(0, 8);
                    file.WS08_10_912_06 = tjbg.WS08_10_052_18;
                    file.CT08_10_912_06 = tjbg.CT08_10_052_18;
                    file.WS08_10_052_28 = tjbg.WS08_10_052_18;
                    file.WS08_10_052_29 = tjbg.CT08_10_052_18;
                    file.WS08_10_052_03 = tjbg.WS08_10_052_18;
                    file.CT08_10_052_03 = tjbg.CT08_10_052_18;
                    file.WS99_99_900_96 = "4";
                    file.CT99_99_900_96 = "医院体检报告";
                    file.WS99_99_900_97 = "pdf";
                    file.BASE64STR = tjbgPdf.BGNR;
                    //FJGHSJSCFW.FileUploadServiceClient client = new FileUploadServiceClient();
                    string inXml = file.GetInXml();
                    //client.resourceMethod(ref inXml);
                    DeclareOutData outData = new DeclareOutData(inXml);
                    tjbgPdf.SCBZ = 1;
                    tjbgPdfService.UpdateScbz(tjbgPdf);
                }
            });
        }

        private string CallWebService(string webUrl, string inXml, string contentType)
        {
            string result = string.Empty;
            string param = string.Empty;
            byte[] bytes = null;

            Stream writer = null;
            HttpWebRequest request = null;
            HttpWebResponse response = null;
            StreamReader reader = null;
            param = inXml;
            bytes = Encoding.UTF8.GetBytes(param);

            request = (HttpWebRequest)WebRequest.Create(webUrl);
            request.Method = "POST";
            request.ContentType = contentType;
            request.ContentLength = bytes.Length;

            try
            {
                writer = request.GetRequestStream();        //获取用于写入请求数据的Stream对象
            }
            catch (Exception ex)
            {
                return "";
            }

            writer.Write(bytes, 0, bytes.Length);       //把参数数据写入请求数据流
            writer.Close();

            try
            {
                response = (HttpWebResponse) request.GetResponse(); //获得响应
                #region 这种方式读取到的是一个Xml格式的字符串
                reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8);
                result = reader.ReadToEnd();
                #endregion 这种方式读取到的是一个Xml格式的字符串
                return result;
            }
            catch (WebException ex)
            {
                return "";
            }
            finally
            {
                response.Dispose();
                response.Close();

                reader.Close();
                reader.Dispose();
            }
        }
    }
}